< Back
# Simplest look at Reactive. Code first, see how it works in action. This might help to grasp the concept easier. Go to https://start.spring.io/ add **Spring Reactive Web** and **Lombok** ## Using annotation way to define controller. ```java package com.kone.sandbox.reactiverest.controller; import com.kone.sandbox.reactiverest.dto.Echo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController public class EchoController { @GetMapping("/echo") public Mono<Echo> echo() { var resp = Echo.builder().message("echo...").build(); return Mono.just(resp); } } ``` Echo dto ```java package com.kone.sandbox.reactiverest.dto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Echo { private String message; } ``` That is all! Then create The test. ```java package com.kone.sandbox.reactiverest.controller; import com.kone.sandbox.reactiverest.dto.Echo; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.context.annotation.Import; import org.springframework.test.web.reactive.server.WebTestClient; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @WebFluxTest @Import({EchoController.class}) class EchoControllerTest { @Autowired private WebTestClient client; @Test void testEcho() { client.get().uri("/echo").exchange().expectStatus().isOk().expectBody(Echo.class).value(v -> { assertThat(v.getMessage()).isEqualTo("echo..."); }); } } ``` using `curl` to test it manually ```shell $ curl localhost:8080/echo {"message":"echo..."} ``` ## Using Functional style Create **Handler** ```java package com.kone.sandbox.reactiverest.handler; import com.kone.sandbox.reactiverest.dto.Greeting; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; @Component public class GreetingHandler { public Mono<ServerResponse> hello(ServerRequest request) { return ServerResponse .ok() .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(Greeting.builder().message("Hello, Spring!").build())); } } ``` Greeting DTO ```java package com.kone.sandbox.reactiverest.dto; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Greeting { private String message; } ``` add Router ```java package com.kone.sandbox.reactiverest.router; import com.kone.sandbox.reactiverest.handler.GreetingHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.accept; @Configuration(proxyBeanMethods = false) public class GreetingRouter { @Bean public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) { return RouterFunctions .route(GET("/hello").and(accept(MediaType.APPLICATION_JSON)), greetingHandler::hello); } } ``` Test it ```java package com.kone.sandbox.reactiverest.router; import com.kone.sandbox.reactiverest.dto.Greeting; import com.kone.sandbox.reactiverest.handler.GreetingHandler; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.reactive.server.WebTestClient; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @WebFluxTest @Import({GreetingRouter.class, GreetingHandler.class}) class GreetingRouterTest { @Autowired private WebTestClient webTestClient; @Test void testHello() { webTestClient.get().uri("/hello") .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody(Greeting.class).value( g -> { assertThat(g.getMessage()).isEqualTo("Hello, Spring!"); }); } } ``` use `curl` manually ```shell $ curl localhost:8080/hello {"message":"Hello, Spring!"} ```